/*
 * Lab07D2.cpp - example returning by value, pointer or reference
 *
 *  Created on: Mar 25, 2014
 *      Author: Anthony Varghese
 */

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

class A{
public:
	A(): data(0){ cout << "     Default Constructor" << endl; }
	A(int d): data(d){ cout << "     Overloaded Constructor" << endl; }
	~A(){  cout << "     Destructor" << endl; }
	A returnInputParameter(const A in){          	    return in;	}
	A returnInputReferenceParameter(const A& in){	    return in;	}
	A returnLocalObject(){	                      A local(2);	    return local;	}
	A& returnLocalObjectReference(){	          A local(3);	    return local;	}
	A* returnPointerLocalObject(){	              A local(4);	    return &local;	}
	A* returnPointerHeapObject(){	              A* heap = new A(5);	    return heap;
	}
private:
	int data;
	friend std::ostream& operator<<(std::ostream& out, const A& x);
};

std::ostream& operator<<(std::ostream& out, const A& x){
	out << "  A object with data: " << x.data;
	return out;
}

int main(){
    cout << "CSIS 237 Lab 7 - Returning objects" << endl;

    A start;
    cout << " Starting object is " << start << endl;

    A rIP = start.returnInputParameter(start);
    cout << " Using a return of input parameter start, we get " << rIP << endl;

    A rIRP = start.returnInputReferenceParameter(start);
    cout << " Using a return of input reference parameter to start, we get " << rIRP << endl;

    A rLO = start.returnLocalObject();
    cout << " Using a return of a local object in function, we get " << rLO << endl;

    A& rLOR = start.returnLocalObjectReference();
    cout << " Using a return of a reference to local object in function, we get " << rLOR << endl;

    A* rPLO = start.returnPointerLocalObject();
    cout << " Using a return of a pointer to a local object in function, we get " << *rPLO << endl;

    A* rPHO = start.returnPointerHeapObject();
    cout << " Using a return of a heap object from function, we get " << *rPHO << endl;

    cout << "... done" << endl;
}
